<?php

namespace Eugenes\LaravelBuilder;

use Eugenes\LaravelBuilder\Builder\WhereHasIn;
use Eugenes\LaravelBuilder\Builder\WhereHasJoin;
use Eugenes\LaravelBuilder\Builder\WhereHasMorphIn;
use Eugenes\LaravelBuilder\Builder\WhereHasNotIn;
use Illuminate\Database\Eloquent;
use Illuminate\Support\ServiceProvider;


class LaravelBuilderProvider extends ServiceProvider
{
    public function register()
    {
        Eloquent\Builder::macro('whereHasIn', function ($relationName, $callable = null) {
            return (new WhereHasIn($this, $relationName, function ($nextRelation, $builder) use ($callable) {
                if ($nextRelation) {
                    return $builder->whereHasIn($nextRelation, $callable);
                }
                if ($callable) {
                    return $builder->callScope($callable);
                }
                return $builder;
            }))->execute();
        });


        Eloquent\Builder::macro('whereHasJoin', function ($relationName, $callable = null) {
            return (new WhereHasJoin($this, $relationName, function (Eloquent\Builder $builder, Eloquent\Builder $relationBuilder) use ($callable) {
                if ($callable) {
                    $relationBuilder->callScope($callable);
                    return $builder->addNestedWhereQuery($relationBuilder->getQuery());
                }
                return $builder;
            }))->execute();
        });


        Eloquent\Builder::macro('orWhereHasIn', function ($relationName, $callable = null) {
            return $this->orWhere(function ($query) use ($relationName, $callable) {
                return $query->whereHasIn($relationName, $callable);
            });
        });
        Eloquent\Builder::macro('whereHasNotIn', function ($relationName, $callable = null) {
            return (new WhereHasNotIn($this, $relationName, function ($nextRelation, $builder) use ($callable) {
                if ($nextRelation) {
                    return $builder->whereHasNotIn($nextRelation, $callable);
                }

                if ($callable) {
                    return $builder->callScope($callable);
                }

                return $builder;
            }))->execute();
        });

        Eloquent\Builder::macro('orWhereHasNotIn', function ($relationName, $callable = null) {
            return $this->orWhere(function ($query) use ($relationName, $callable) {
                return $query->whereHasNotIn($relationName, $callable);
            });
        });


        foreach (['pluck', 'sum', 'whereBetween', 'whereIn', 'where', 'orderBy', 'orderByDesc'] as $macroAction) {
            Eloquent\Builder::macro('yj' . $macroAction, function (...$params) use ($macroAction) {
                $params[0] = $this->getModel()->getTable() . '.' . $params[0];
                return $this->{$macroAction}(...$params);
            });
            
        }

        Eloquent\Builder::macro('yjselect', function ($columns = ['*']) {
            $table = $this->getModel()->getTable();
            $columns = is_array($columns) ? $columns : func_get_args();
            foreach ($columns as &$column) {
                $column = $table . '.' . $column;
            }
            return $this->select($columns);
        });


        Eloquent\Builder::macro('whereHasMorphIn', WhereHasMorphIn::make());
        Eloquent\Builder::macro('orWhereHasMorphIn', function ($relation, $types, $callback = null) {
            return $this->whereHasMorphIn($relation, $types, $callback, 'or');
        });
    }
}
